import json
import subprocess

from leapp.actors import Actor
from leapp.tags import ConfigurationSynchronizationPhaseTag, IPUWorkflowTag
from leapp.models import ConfigurationSynchronization


class ServiceConfigurationSynchronizer(Actor):
    """
    No documentation has been provided for the service_configuration_synchronizer actor.
    """

    name = 'service_configuration_synchronizer'
    consumes = (ConfigurationSynchronization, )
    produces = ()
    tags = (IPUWorkflowTag, ConfigurationSynchronizationPhaseTag, )

    def service_configuration_backup(self):
        try:
            self.log.info("backing up service configurations after migration.")
            services_config_raw = str(subprocess.check_output("systemctl list-unit-files | egrep 'enabled |disabled ' | awk '{print $1,$2}'", shell=True)).strip()
            services_config = {
                line.strip().split()[0]: line.strip().split()[1][:-1]
                for line in services_config_raw.split('\n')
            }

            return services_config
        except Exception as e:
            self.log.warning(" fail to backup service, ignore it. " + str(e))

        return {}

    def do_config_services(self, config):
        config_report = []
        for service, status in config.items():
            self.log.info("".join((service, " -> ", status)))
            report = {
                "service": service,
                "old status": status,
                "current status": status,
            }

            try:
                print("systemctl %s %s" % (status, service))
                output = str(subprocess.check_call("systemctl %s %s" % (status, service), shell=True)).strip()
                report.update({
                    "information": output,
                    "result": "succeed"
                })

            except Exception as e:
                self.log.warning("fail to %s %s" % (status, service))

                report.update({
                    "information": str(e),
                    "result": "fail",
                })

            config_report += [report]

        return config_report

    def config_services(self, config, backup):
        _config_report = self.do_config_services(config)

        config_report = []
        for line in _config_report:
            if line["result"] == "fail":
                line["current status"] = backup.get(line["service"] , "does not exist")

            config_report += [line]

        return config_report

    def service_configuration_restore(self, backup_configuration):
        try:
            self.log.info("Starting to roll back services configurations.")
            self.do_config_services(backup_configuration)

        except Exception as e:
            self.log.warning("fail to roll back services configurations: " + str(e))
            self.log.warning("default service configuration : " + str(backup_configuration))
            with open("/var/log/leapp/service-default.log", "w") as f:
                json.dump(str(backup_configuration), f, indent=4)

    def process(self):
        backup_configuratuon = self.service_configuration_backup()

        try:
            self.log.info("Starting to synchronize services configurations.")
            for configuration in self.consume(ConfigurationSynchronization):
                services_configuration = json.loads(configuration.services_configuration)
                config_report = self.config_services(services_configuration, backup_configuratuon)

            with open("/var/log/leapp/service-configuration-report.json", "w") as f:
                json.dump(config_report, f, indent=4)
                print("Service configuration output: /var/log/leapp/service-configuration-report.json")

        except Exception as e:
            self.log.warning("fail to synchronize services configurations, rolling back. " + str(e))

